#include "NonSASLAuthentication.h"

#include "XPMMConnection.h"
#include <packet/Authentication.h>
#include "PacketCollector.h"
#include <packet/IQ.h>

std::string NonSASLAuthentication::authenticate(std::string & username, std::string & password, std::string & resource) {
    // If we send an authentication packet in "get" mode with just the username,
    // the server will return the list of authentication protocols it supports.
    Authentication * discoveryAuth = new Authentication();
    discoveryAuth->setType(IQ::Type::GET);
    discoveryAuth->setUsername(username);

    PacketCollector * collector = connection->createPacketCollector(new PacketIDFilter(discoveryAuth->getPacketID()));
    // Send the packet
    connection->sendPacket(discoveryAuth);
    // Wait up to a certain number of seconds for a response from the server.
    IQ * response = collector->nextResult(SmackConfiguration::getPacketReplyTimeout());
    if (response == NULL) {
    	//throw new XMPPException("No response from the server.");
    } else if (response->getType() == IQ::Type::ERROR) {
    	//throw new XMPPException(response.getError());
    }
    // Otherwise, no error so continue processing.
    Authentication * authTypes = (Authentication*) response;
    collector->cancel();

	// Now, create the authentication packet we'll send to the server.
    Authentication * auth = new Authentication();
    auth->setUsername(username);

	// Figure out if we should use digest or plain text authentication.
    if (authTypes->getDigest() != NULL) {
    	auth->setDigest(connection->getConnectionID(), password);
    } else if (authTypes->getPassword() != NULL) {
    	auth->setPassword(password);
    } else {
    	//throw new XMPPException("Server does not support compatible authentication mechanism.");
    }

	auth->setResource(resource);

    collector = connection->createPacketCollector(new PacketIDFilter(auth->getPacketID()));
    // Send the packet.
    connection->sendPacket(auth);
    // Wait up to a certain number of seconds for a response from the server.
    response = (IQ*)collector->nextResult(SmackConfiguration::getPacketReplyTimeout());
    if (response == NULL) {
    	//throw new XMPPException("Authentication failed.");
    } else if (response->getType() == IQ::Type::ERROR) {
    	//throw new XMPPException(response.getError());
    }
    // We're done with the collector, so explicitly cancel it.
    collector->cancel();

    return response->getTo();
}

std::string NonSASLAuthentication::authenticateAnonymously() {
    // Create the authentication packet we'll send to the server.
    Authentication * auth = new Authentication();

    PacketCollector * collector = 
		connection->createPacketCollector(new PacketIDFilter(auth->getPacketID()));
    // Send the packet.
    connection->sendPacket(auth);
    // Wait up to a certain number of seconds for a response from the server.
    IQ * response = (IQ*)collector->nextResult(SmackConfiguration::getPacketReplyTimeout());
    if (response == NULL) {
    	//throw new XMPPException("Anonymous login failed.");
    } else if (response->getType() == IQ::Type::ERROR) {
        //throw new XMPPException(response.getError());
    }
    // We're done with the collector, so explicitly cancel it.
    collector->cancel();

    if (response->getTo() != NULL) {
    	return response->getTo();
    } else {
        return connection->serviceName + "/" + ((Authentication*)response->getResource();
    }
}
